"""
管理员管理API
"""
from flask import request, jsonify, g
from flask_jwt_extended import jwt_required, get_jwt_identity
from app.api.v1.admin import admin_blueprint
from app.models.system import Admin, AdminLog, Role, Permission, AdminRole, Tenant
from app.core.extensions import db
from app.services.decorators import admin_required
from datetime import datetime
import re


def admin_to_dict(admin):
    """管理员对象转字典"""
    return {
        'id': admin.id,
        'username': admin.username,
        'email': admin.email,
        'is_super': admin.is_super,
        'tenant_id': admin.tenant_id,
        'is_test': getattr(admin, 'is_test', 0),
        'tenant_name': admin.tenant.name if hasattr(admin, 'tenant') and admin.tenant else None,
        'last_login': admin.last_login.strftime('%Y-%m-%d %H:%M:%S') if admin.last_login else None,
        'create_time': admin.create_time.strftime('%Y-%m-%d %H:%M:%S') if admin.create_time else None,
        'roles': [{'id': role.id, 'name': role.name, 'description': role.description}
                 for role in admin.roles] if hasattr(admin, 'roles') and admin.roles else []
    }


def validate_admin_data(data, is_update=False):
    """验证管理员数据"""
    errors = []

    if not is_update or 'username' in data:
        username = data.get('username', '').strip()
        if not username:
            errors.append('用户名不能为空')
        elif len(username) < 3 or len(username) > 64:
            errors.append('用户名长度必须在3-64个字符之间')
        elif not re.match(r'^[a-zA-Z0-9_]+$', username):
            errors.append('用户名只能包含字母、数字和下划线')

    if not is_update or 'email' in data:
        email = data.get('email', '').strip()
        if email and not re.match(r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$', email):
            errors.append('邮箱格式不正确')
        elif email and len(email) > 120:
            errors.append('邮箱长度不能超过120个字符')

    if not is_update and 'password' in data:
        password = data.get('password', '')
        if not password:
            errors.append('密码不能为空')
        elif len(password) < 6:
            errors.append('密码长度不能少于6位')

    return errors


@admin_blueprint.route('/admins', methods=['GET'])
@jwt_required()
@admin_required
def get_admins():
    """获取管理员列表"""
    try:
        page = request.args.get('page', 1, type=int)
        per_page = min(request.args.get('per_page', 10, type=int), 100)
        username = request.args.get('username', '').strip()
        email = request.args.get('email', '').strip()
        is_super = request.args.get('is_super', type=int)
        is_test = request.args.get('is_test', type=int)
        tenant_id = request.args.get('tenant_id', type=int)

        # 构建查询
        query = Admin.query

        # 搜索条件
        if username:
            query = query.filter(Admin.username.like(f'%{username}%'))
        if email:
            query = query.filter(Admin.email.like(f'%{email}%'))
        if is_super is not None:
            query = query.filter(Admin.is_super == is_super)
        if is_test is not None:
            query = query.filter(Admin.is_test == is_test)
        if tenant_id is not None:
            query = query.filter(Admin.tenant_id == tenant_id)

        # 排序
        query = query.order_by(Admin.create_time.desc())
        
        # 分页
        pagination = query.paginate(
            page=page, 
            per_page=per_page, 
            error_out=False
        )
        
        admins = pagination.items
        
        return jsonify({
            'code': 0,
            'message': '获取成功',
            'data': {
                'total': pagination.total,
                'pages': pagination.pages,
                'page': page,
                'per_page': per_page,
                'items': [admin_to_dict(admin) for admin in admins]
            }
        })
        
    except Exception as e:
        return jsonify({'code': 1, 'message': f'获取管理员列表失败: {str(e)}'}), 500


@admin_blueprint.route('/admins/<int:admin_id>', methods=['GET'])
@jwt_required()
@admin_required
def get_admin(admin_id):
    """获取管理员详情"""
    try:
        admin = Admin.query.get_or_404(admin_id)
        
        return jsonify({
            'code': 0,
            'message': '获取成功',
            'data': admin_to_dict(admin)
        })
        
    except Exception as e:
        return jsonify({'code': 1, 'message': f'获取管理员详情失败: {str(e)}'}), 500


@admin_blueprint.route('/admins', methods=['POST'])
@jwt_required()
@admin_required
def create_admin():
    """创建管理员"""
    try:
        data = request.get_json()
        
        # 验证数据
        errors = validate_admin_data(data)
        if errors:
            return jsonify({'code': 1, 'message': '; '.join(errors)}), 400
        
        # 检查用户名是否已存在
        if Admin.query.filter_by(username=data['username']).first():
            return jsonify({'code': 1, 'message': '用户名已存在'}), 400
        
        # 检查邮箱是否已存在
        if data.get('email') and Admin.query.filter_by(email=data['email']).first():
            return jsonify({'code': 1, 'message': '邮箱已存在'}), 400

        # 验证租户ID
        tenant_id = data.get('tenant_id', 1)  # 默认租户ID为1
        if tenant_id:
            tenant = Tenant.query.get(tenant_id)
            if not tenant:
                return jsonify({'code': 1, 'message': '租户不存在'}), 400

        # 创建管理员
        from app.utils.password import generate_password_hash
        admin = Admin(
            username=data['username'],
            password_hash=generate_password_hash(data['password']),
            email=data.get('email'),
            is_super=data.get('is_super', False),
            is_test=data.get('is_test', False),
            tenant_id=tenant_id
        )
        admin.create_time = datetime.now()
        
        db.session.add(admin)
        db.session.flush()  # 获取ID
        
        # 分配角色
        role_ids = data.get('role_ids', [])
        if role_ids:
            roles = Role.query.filter(Role.id.in_(role_ids)).all()
            for role in roles:
                admin_role = AdminRole(admin_id=admin.id, role_id=role.id)
                db.session.add(admin_role)
        
        # 添加操作日志
        log = AdminLog(
            admin_id=get_jwt_identity(),
            action='创建管理员',
            ip=request.remote_addr,
            details=f'创建管理员 {admin.username} (ID: {admin.id})'
        )
        db.session.add(log)
        
        db.session.commit()
        
        return jsonify({
            'code': 0,
            'message': '创建成功',
            'data': admin_to_dict(admin)
        })
        
    except Exception as e:
        db.session.rollback()
        return jsonify({'code': 1, 'message': f'创建管理员失败: {str(e)}'}), 500


@admin_blueprint.route('/admins/<int:admin_id>', methods=['PUT'])
@jwt_required()
@admin_required
def update_admin(admin_id):
    """更新管理员信息"""
    try:
        admin = Admin.query.get_or_404(admin_id)
        data = request.get_json()
        
        # 验证数据
        errors = validate_admin_data(data, is_update=True)
        if errors:
            return jsonify({'code': 1, 'message': '; '.join(errors)}), 400
        
        # 检查用户名是否已存在（排除自己）
        if 'username' in data:
            existing = Admin.query.filter(Admin.username == data['username'], Admin.id != admin_id).first()
            if existing:
                return jsonify({'code': 1, 'message': '用户名已存在'}), 400
        
        # 检查邮箱是否已存在（排除自己）
        if 'email' in data and data['email']:
            existing = Admin.query.filter(Admin.email == data['email'], Admin.id != admin_id).first()
            if existing:
                return jsonify({'code': 1, 'message': '邮箱已存在'}), 400
        
        # 验证租户ID
        if 'tenant_id' in data and data['tenant_id']:
            tenant = Tenant.query.get(data['tenant_id'])
            if not tenant:
                return jsonify({'code': 1, 'message': '租户不存在'}), 400

        # 更新管理员信息
        if 'username' in data:
            admin.username = data['username']
        if 'email' in data:
            admin.email = data['email']
        if 'is_super' in data:
            admin.is_super = data['is_super']
        if 'tenant_id' in data:
            admin.tenant_id = data['tenant_id']
        if 'is_test' in data:
            admin.is_test = data['is_test']
        if 'password' in data and data['password']:
            from app.utils.password import generate_password_hash
            admin.password_hash = generate_password_hash(data['password'])
        
        # 更新角色
        if 'role_ids' in data:
            # 删除现有角色关联
            AdminRole.query.filter_by(admin_id=admin_id).delete()
            
            # 添加新的角色关联
            role_ids = data['role_ids']
            if role_ids:
                roles = Role.query.filter(Role.id.in_(role_ids)).all()
                for role in roles:
                    admin_role = AdminRole(admin_id=admin_id, role_id=role.id)
                    db.session.add(admin_role)
        
        # 添加操作日志
        log = AdminLog(
            admin_id=get_jwt_identity(),
            action='更新管理员',
            ip=request.remote_addr,
            details=f'更新管理员 {admin.username} (ID: {admin.id})'
        )
        db.session.add(log)
        
        db.session.commit()
        
        return jsonify({
            'code': 0,
            'message': '更新成功',
            'data': admin_to_dict(admin)
        })

    except Exception as e:
        db.session.rollback()
        return jsonify({'code': 1, 'message': f'更新管理员失败: {str(e)}'}), 500


@admin_blueprint.route('/admins/<int:admin_id>', methods=['DELETE'])
@jwt_required()
@admin_required
def delete_admin(admin_id):
    """删除管理员"""
    try:
        admin = Admin.query.get_or_404(admin_id)

        # 不能删除自己
        current_admin_id = get_jwt_identity()
        if admin_id == current_admin_id:
            return jsonify({'code': 1, 'message': '不能删除自己'}), 400

        # 不能删除超级管理员（除非自己也是超级管理员）
        current_admin = Admin.query.get(current_admin_id)
        if admin.is_super and not current_admin.is_super:
            return jsonify({'code': 1, 'message': '无权删除超级管理员'}), 403

        # 删除角色关联
        AdminRole.query.filter_by(admin_id=admin_id).delete()

        # 添加操作日志
        log = AdminLog(
            admin_id=current_admin_id,
            action='删除管理员',
            ip=request.remote_addr,
            details=f'删除管理员 {admin.username} (ID: {admin.id})'
        )
        db.session.add(log)

        # 删除管理员
        db.session.delete(admin)
        db.session.commit()

        return jsonify({
            'code': 0,
            'message': '删除成功'
        })

    except Exception as e:
        db.session.rollback()
        return jsonify({'code': 1, 'message': f'删除管理员失败: {str(e)}'}), 500


@admin_blueprint.route('/admins/<int:admin_id>/test-status', methods=['PUT'])
@jwt_required()
@admin_required
def update_admin_test_status(admin_id):
    """更新管理员测试状态"""
    try:
        admin = Admin.query.get_or_404(admin_id)
        data = request.get_json()

        if 'is_test' not in data:
            return jsonify({'code': 1, 'message': '测试状态参数不能为空'}), 400

        is_test = data['is_test']
        if is_test not in [0, 1]:
            return jsonify({'code': 1, 'message': '测试状态值无效'}), 400

        admin.is_test = is_test

        # 添加操作日志
        status_text = '设为测试账号' if is_test == 1 else '取消测试账号'
        log = AdminLog(
            admin_id=get_jwt_identity(),
            action=f'{status_text}',
            ip=request.remote_addr,
            details=f'{status_text} {admin.username} (ID: {admin.id})'
        )
        db.session.add(log)

        db.session.commit()

        return jsonify({
            'code': 0,
            'message': f'{status_text}成功',
            'data': admin_to_dict(admin)
        })

    except Exception as e:
        db.session.rollback()
        return jsonify({'code': 1, 'message': f'更新测试状态失败: {str(e)}'}), 500


@admin_blueprint.route('/admins/<int:admin_id>/roles', methods=['GET'])
@jwt_required()
@admin_required
def get_admin_roles(admin_id):
    """获取管理员的角色列表"""
    try:
        admin = Admin.query.get_or_404(admin_id)

        return jsonify({
            'code': 0,
            'message': '获取成功',
            'data': {
                'admin_id': admin_id,
                'admin_name': admin.username,
                'roles': [{'id': role.id, 'name': role.name, 'description': role.description}
                         for role in admin.roles]
            }
        })

    except Exception as e:
        return jsonify({'code': 1, 'message': f'获取角色列表失败: {str(e)}'}), 500


@admin_blueprint.route('/admins/<int:admin_id>/roles', methods=['PUT'])
@jwt_required()
@admin_required
def update_admin_roles(admin_id):
    """更新管理员的角色"""
    try:
        admin = Admin.query.get_or_404(admin_id)
        data = request.get_json()

        role_ids = data.get('role_ids', [])

        # 验证角色ID
        if role_ids:
            valid_roles = Role.query.filter(Role.id.in_(role_ids)).all()
            if len(valid_roles) != len(role_ids):
                return jsonify({'code': 1, 'message': '存在无效的角色ID'}), 400

        # 删除现有角色关联
        AdminRole.query.filter_by(admin_id=admin_id).delete()

        # 添加新的角色关联
        for role_id in role_ids:
            admin_role = AdminRole(admin_id=admin_id, role_id=role_id)
            db.session.add(admin_role)

        # 添加操作日志
        log = AdminLog(
            admin_id=get_jwt_identity(),
            action='更新管理员角色',
            ip=request.remote_addr,
            details=f'更新管理员 {admin.username} 的角色，角色ID: {role_ids}'
        )
        db.session.add(log)

        db.session.commit()

        # 重新获取管理员信息（包含新的角色）
        admin = Admin.query.get(admin_id)

        return jsonify({
            'code': 0,
            'message': '角色更新成功',
            'data': admin_to_dict(admin)
        })

    except Exception as e:
        db.session.rollback()
        return jsonify({'code': 1, 'message': f'更新角色失败: {str(e)}'}), 500


@admin_blueprint.route('/admins/<int:admin_id>/permissions', methods=['GET'])
@jwt_required()
@admin_required
def get_admin_permissions(admin_id):
    """获取管理员的所有权限（通过角色获得）"""
    try:
        admin = Admin.query.get_or_404(admin_id)

        # 获取管理员通过角色获得的所有权限
        permissions = set()
        for role in admin.roles:
            for permission in role.permissions:
                permissions.add(permission)

        permission_list = [{
            'id': perm.id,
            'name': perm.name,
            'code': perm.code,
            'description': perm.description,
            'resource': perm.resource,
            'action': perm.action
        } for perm in permissions]

        return jsonify({
            'code': 0,
            'message': '获取成功',
            'data': {
                'admin_id': admin_id,
                'admin_name': admin.username,
                'permissions': permission_list
            }
        })

    except Exception as e:
        return jsonify({'code': 1, 'message': f'获取权限列表失败: {str(e)}'}), 500


@admin_blueprint.route('/admins/<int:admin_id>/tenant', methods=['PUT'])
@jwt_required()
@admin_required
def update_admin_tenant(admin_id):
    """更新管理员的租户"""
    try:
        admin = Admin.query.get_or_404(admin_id)
        data = request.get_json()

        tenant_id = data.get('tenant_id')

        # 验证租户ID
        if tenant_id:
            tenant = Tenant.query.get(tenant_id)
            if not tenant:
                return jsonify({'code': 1, 'message': '租户不存在'}), 400

        old_tenant_id = admin.tenant_id
        admin.tenant_id = tenant_id
        admin.updated_at = datetime.now()

        # 添加操作日志
        log = AdminLog(
            admin_id=get_jwt_identity(),
            action='更新管理员租户',
            ip=request.remote_addr,
            details=f'更新管理员 {admin.username} 的租户从 {old_tenant_id} 到 {tenant_id}'
        )
        db.session.add(log)

        db.session.commit()

        return jsonify({
            'code': 0,
            'message': '租户更新成功',
            'data': admin_to_dict(admin)
        })

    except Exception as e:
        db.session.rollback()
        return jsonify({'code': 1, 'message': f'更新租户失败: {str(e)}'}), 500


@admin_blueprint.route('/admins/reset-password/<int:admin_id>', methods=['PUT'])
@jwt_required()
@admin_required
def reset_admin_password(admin_id):
    """重置管理员密码"""
    try:
        admin = Admin.query.get_or_404(admin_id)
        data = request.get_json()

        new_password = data.get('new_password')
        if not new_password:
            return jsonify({'code': 1, 'message': '新密码不能为空'}), 400

        if len(new_password) < 6:
            return jsonify({'code': 1, 'message': '密码长度不能少于6位'}), 400

        from app.utils.password import generate_password_hash
        admin.password_hash = generate_password_hash(new_password)

        # 添加操作日志
        log = AdminLog(
            admin_id=get_jwt_identity(),
            action='重置管理员密码',
            ip=request.remote_addr,
            details=f'重置管理员 {admin.username} (ID: {admin.id}) 的密码'
        )
        db.session.add(log)

        db.session.commit()

        return jsonify({
            'code': 0,
            'message': '密码重置成功'
        })

    except Exception as e:
        db.session.rollback()
        return jsonify({'code': 1, 'message': f'重置密码失败: {str(e)}'}), 500
